package com.bdqn.t320.security.config;

import com.bdqn.t320.security.service.UserService;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.annotation.Resource;
import javax.sql.DataSource;

/**
 * security配置类
 */
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    DataSource dataSource;

    @Resource
    UserService userService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()//关闭csrf网络安全
                .formLogin() //开启登录页面,默认登录页面/login
                .successForwardUrl("/dologin")  //登录成功之后跳转的地址
                .loginPage("/login").permitAll() //配置登录页面并对该页面进行授权配置
                .loginProcessingUrl("/dologin")//登录controller请求
                //.usernameParameter("username") //指定登录界面用户名文本框的name值，如果没有指定，默认属性名必须为username
                //.passwordParameter("password")//指定登录界面密码密码框的name值，如果没有指定，默认属性名必须为password
                .and()
                .logout().logoutUrl("/logout").logoutSuccessHandler(new LogoutSuccessHandlerConfig()).clearAuthentication(true).invalidateHttpSession(true)
                .and()
                .authorizeRequests()
                .antMatchers("/images/**", "/js/**", "/css/**", "/fonts/**", "/localcss/**", "/localjs/**").permitAll()  //放行静态资源
                .antMatchers("/timeout").permitAll()
                .antMatchers("/logout").permitAll()
                .anyRequest().access("@myRBACService.hasPermission(request,authentication)")
                /*     .antMatchers("/admin").hasRole("admin")  //针对admin角色能访问/admin
                     .antMatchers("/user").hasAuthority("ROLE_user")    //针对user角色能访问/user*/
                //.and()
                //.authorizeRequests().anyRequest().authenticated()//任何请求都需要经过验证
                .and()
                .sessionManagement()
                .invalidSessionUrl("/timeout")
                .and()
                .rememberMe()
                .tokenValiditySeconds(2000)
                .rememberMeParameter("remember-me")
                .tokenRepository(persistentTokenRepository())//设置token仓库
        //.rememberMeCookieName()  //客户端保存cookie的值
        ;
    }


    //    7、使用自己的帐号和密码登录，实现基于内存的帐号密码存储，添加自定义用户名和密码后，
//    后台就不会输出默认的user密码。
//    在SecurityConfig类中重写configure(AuthenticationManagerBuilder auth)方法
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //基于内存认证授权
        /*auth.inMemoryAuthentication()
                //passwordEncoder(NoOpPasswordEncoder.getInstance())
                .passwordEncoder(new BCryptPasswordEncoder())
                .withUser("admin").password("$2a$10$Ohc/T1Do24RYx1kIxhGmt.vR6ssrieM7bWrb5HnhGgcE6A//tJ02y").roles("admin")
                .and()
                .withUser("user").password("$2a$10$l0roAPfDgirQiOORghif1e1y9y1.Zqz7r3JERYZjP57nE/D6KEz4G").roles("user");*/

        //基于数据库认证授权
        auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder());
    }

    public PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        //设置数据源
        tokenRepository.setDataSource(dataSource);
        //自动创建表,这里就不让程序自动创建表，咱们自己主动创建
        //创建表的sql语句在JdbcTokenRepositoryImpl类中的initDao方法
        //create table persistent_logins (username varchar(64) not null, series varchar(64) primary key, token varchar(64) not null, last_used timestamp not null)
        //tokenRepository.setCreateTableOnStartup(true);
        return tokenRepository;
    }
}
